/* mm5_file.h */

#ifndef DODO_MM5_FILE_H
#define DODO_MM5_FILE_H

#include <string>
#include <fstream>
#include <map>
#include <exception>
#include "defines.h"
#include "var_info.h"
#include "big_header.h"

namespace dodomet
{
namespace mm5
{

/// MM5_File represents the key infomation of a MM5 model file.
/**
 * It holds a Big_Header, and a list of variables.
 */
class MM5_File
{
public:
	MM5_File();

	/// initialising with a file name.
	/**
	 * It may throw a exceptions::cannot_open_file exception;
	 */
	MM5_File(const std::string& filename);
	
	MM5_File(const MM5_File& orig);
	MM5_File& operator= (const MM5_File& orig);

public:
	/// returns file name;
	std::string filename() const;

	/// if this MM5_File has not been initialised with a file, 
	/**
	 * or you want to load another file, use this function.
	 * It may throw a exceptions::cannot_open_file exception;
	 */
	void read_file(const std::string& filename);

public:
	/// iterator type to the variables
	typedef std::list<Var_Info>::iterator iterator;

	/// const_iterator type to the variables
	typedef std::list<Var_Info>::const_iterator const_iterator;

	/// returns const_iterator to the begin of the variable list
	const_iterator begin() const;

	/// returns const_iterator to the end of the variable list;
	/**
	 * remember end means the position next to the last element.
	 */
	const_iterator end() const;

	/// returns iterator to the begin of the variable list
	iterator begin();

	/// returns iterator to the end of the variable list;
	/**
	 * remember end means the position next to the last element.
	 */
	iterator end();

	/// returns total number of the variables.
	int var_num() const;

	/// returns const_iterator to the variable with that name. 
	/**
	 * when not found, returns end();
	 */
	const_iterator find_var_name(const std::string& var_name) const;

	/// returns iterator to the variable with that name. 
	/**
	 * when not found, returns end();
	 */
	iterator find_var_name(const std::string& var_name);

	/// returns the Big_Header of the file.
	Big_Header big_header() const;

	/// returns the start time of the program according to the file type. 
	/**
	 * if file type is TERRAIN, it will return boost::date_time::not_a_date_time
	 */
	boost::posix_time::ptime start_time() const;

	/// returns the data_type of the MM5 file.
	/**
	 * see MM5 IO doc and defines.h for the available data_type(aka program_indexes).
	 */
	int data_type() const;

private:
	/// skip the field part of the variable, 
	/**
	 * so that the file pointer will jump to the next header directly.
	 * not for user.
	 */
	void ignore_field(const Var_Info& info, std::fstream& file);
private:
	std::string filename_;
	std::list<Var_Info> var_info_list_;
	// BHI BHIC BHR BHRC
	Big_Header big_header_;
private:
	class cannot_open_mm5_file : public std::exception
	{};
};

}  // namespace dodomet::mm5
}  // namespace dodomet

#endif //DODO_MM5_FILE_H

